#!/bin/bash
# 实名不实人检测系统 - 智能运行脚本
# 自动检查和配置环境
# 支持系统: macOS, CentOS 7

set -e  # 遇到错误立即退出

# ============================================
# 系统检测
# ============================================
detect_os() {
    if [[ "$OSTYPE" == "darwin"* ]]; then
        OS_TYPE="macos"
    elif [[ -f /etc/centos-release ]]; then
        OS_TYPE="centos"
    elif [[ -f /etc/redhat-release ]]; then
        OS_TYPE="rhel"
    else
        OS_TYPE="linux"
    fi
    echo "✓ 检测到操作系统: ${OS_TYPE}"
}

# ============================================
# 配置区域
# ============================================
PYTHON_VERSION="3.13"
# PySpark 版本：GraphFrames 需要 PySpark 3.x，不支持 4.0+
# 如果使用 gf 模型，必须使用 PySpark 3.5.x
# setuptools：Python 3.12+ 需要，提供 distutils
REQUIRED_PACKAGES="pyspark>=3.2.0,<4.0 networkx PyYAML graphframes setuptools"

# 根据操作系统设置 Java 路径
set_java_paths() {
    case "$OS_TYPE" in
        macos)
            # macOS Homebrew 路径（优先查找较新版本）
            JAVA_PATHS=(
                "/opt/homebrew/opt/openjdk@17"
                "/opt/homebrew/opt/openjdk@11"
                "/opt/homebrew/opt/openjdk"
                "/usr/local/opt/openjdk@17"
                "/usr/local/opt/openjdk@11"
                "/usr/local/opt/openjdk"
            )
            JAVA_INSTALL_CMD="brew install openjdk@17"
            ;;
        centos|rhel|linux)
            # CentOS/RHEL 常见路径（优先查找较新版本）
            JAVA_PATHS=(
                "/usr/lib/jvm/java-17-openjdk"
                "/usr/lib/jvm/java-17"
                "/usr/lib/jvm/java-11-openjdk"
                "/usr/lib/jvm/java-11"
                "/usr/lib/jvm/java-1.8.0-openjdk"
                "/usr/lib/jvm/java-8-openjdk"
                "/usr/lib/jvm/jre-1.8.0-openjdk"
            )
            JAVA_INSTALL_CMD="sudo yum install -y java-1.8.0-openjdk java-1.8.0-openjdk-devel"
            ;;
    esac
}

# ============================================
# 环境检查和配置函数
# ============================================

# 检查 Python 版本
check_python_version() {
    if ! command -v python3 &> /dev/null; then
        echo "❌ 错误: 未找到 python3"
        echo "请先安装 Python 3.13+"
        exit 1
    fi

    CURRENT_VERSION=$(python3 --version 2>&1 | awk '{print $2}' | cut -d. -f1,2)
    echo "✓ 找到 Python ${CURRENT_VERSION}"
}

# 检查 Java
check_java() {
    # 首先检查系统是否已有 java 命令
    if command -v java &> /dev/null; then
        JAVA_VERSION_STRING=$(java -version 2>&1 | head -n 1)
        # 提取主版本号 (支持 1.8.x 和 11/17 格式)
        if [[ $JAVA_VERSION_STRING =~ \"1\.8 ]]; then
            JAVA_MAJOR_VERSION="8"
        else
            JAVA_MAJOR_VERSION=$(echo "$JAVA_VERSION_STRING" | awk -F '"' '{print $2}' | cut -d. -f1)
        fi

        # 检查版本是否满足要求 (Java 8+)
        if [ "$JAVA_MAJOR_VERSION" -ge 8 ] 2>/dev/null; then
            # 如果已设置 JAVA_HOME 且有效，直接使用
            if [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ]; then
                echo "✓ 检测到 Java $JAVA_MAJOR_VERSION (JAVA_HOME=$JAVA_HOME)"
            else
                # 尝试从 java 命令反推 JAVA_HOME
                JAVA_BIN=$(command -v java)
                # macOS 使用不同的方式处理符号链接
                if [[ "$OS_TYPE" == "macos" ]]; then
                    # 使用 /usr/libexec/java_home 如果可用
                    if command -v /usr/libexec/java_home &> /dev/null; then
                        JAVA_HOME=$(/usr/libexec/java_home 2>/dev/null)
                    else
                        # 手动解析符号链接
                        while [ -L "$JAVA_BIN" ]; do
                            JAVA_BIN=$(readlink "$JAVA_BIN")
                        done
                        JAVA_HOME="${JAVA_BIN%/bin/java}"
                    fi
                else
                    # Linux 使用 readlink -f
                    JAVA_HOME=$(readlink -f "$JAVA_BIN" 2>/dev/null || echo "$JAVA_BIN")
                    JAVA_HOME="${JAVA_HOME%/bin/java}"
                fi
                JAVA_HOME="${JAVA_HOME%/jre}"
                export JAVA_HOME
                echo "✓ 检测到 Java $JAVA_MAJOR_VERSION (自动设置 JAVA_HOME=$JAVA_HOME)"
            fi

            # 给出版本建议
            if [ "$JAVA_MAJOR_VERSION" = "8" ]; then
                echo "  ℹ️  提示: 当前使用 Java 8"
            fi
            return 0
        fi
    fi

    # 如果没有找到 Java 或版本过低，尝试查找其他版本
    echo "⚠️  未找到合适的 Java 版本，尝试查找已安装的 Java..."

    FOUND_JAVA=""
    for java_path in "${JAVA_PATHS[@]}"; do
        if [ -d "$java_path" ] && [ -x "$java_path/bin/java" ]; then
            FOUND_JAVA="$java_path"
            FOUND_VERSION=$("$java_path/bin/java" -version 2>&1 | head -n 1 | awk -F '"' '{print $2}' | cut -d. -f1)
            echo "  找到 Java $FOUND_VERSION: $java_path"
            break
        fi
    done

    # 在 Linux 上尝试使用 alternatives 系统
    if [ -z "$FOUND_JAVA" ] && [[ "$OS_TYPE" != "macos" ]] && command -v alternatives &> /dev/null; then
        ALT_JAVA=$(alternatives --display java 2>/dev/null | grep "link currently points to" | awk '{print $5}' | sed 's|/bin/java||')
        if [ -d "$ALT_JAVA" ] && [ -x "$ALT_JAVA/bin/java" ]; then
            FOUND_JAVA="$ALT_JAVA"
            echo "  通过 alternatives 找到 Java: $FOUND_JAVA"
        fi
    fi

    if [ -z "$FOUND_JAVA" ]; then
        echo "❌ 错误: 未找到 Java (需要 Java 8 或更高版本)"
        echo "请安装 Java:"
        echo "  ${JAVA_INSTALL_CMD}"
        exit 1
    fi

    export PATH="${FOUND_JAVA}/bin:$PATH"
    export JAVA_HOME="${FOUND_JAVA}"
    FINAL_VERSION=$("$FOUND_JAVA/bin/java" -version 2>&1 | head -n 1 | awk -F '"' '{print $2}')
    echo "✓ Java 配置完成 (版本: $FINAL_VERSION, JAVA_HOME=$JAVA_HOME)"
}


# 检查或创建虚拟环境
check_or_create_venv() {
    if [ ! -d "venv" ]; then
        echo ""
        echo "📦 未找到虚拟环境，正在创建..."
        python3 -m venv venv
        echo "✅ 虚拟环境创建成功"
    else
        echo "✓ 虚拟环境已存在"
    fi
}

# 激活虚拟环境
activate_venv() {
    if [ -z "$VIRTUAL_ENV" ]; then
        echo "🔄 激活虚拟环境..."
        source venv/bin/activate
        echo "✅ 虚拟环境已激活"
    else
        echo "✓ 虚拟环境已激活"
    fi
}

# 检查并安装依赖
check_or_install_packages() {
    echo ""
    echo "🔍 检查 Python 依赖包..."

    NEED_INSTALL=0

    # 检查 pyspark
    if ! python -c "import pyspark" 2>/dev/null; then
        echo "  ⚠️  需要安装 pyspark"
        NEED_INSTALL=1
    else
        PYSPARK_VERSION=$(python -c "import pyspark; print(pyspark.__version__)" 2>/dev/null)
        PYSPARK_MAJOR=$(echo "$PYSPARK_VERSION" | cut -d. -f1)

        # 检查版本，必须使用 3.x（支持 nx 和 gf 两种模式）
        if [ "$PYSPARK_MAJOR" != "3" ]; then
            echo "  ⚠️  PySpark ${PYSPARK_VERSION} 不兼容，需要 3.x 版本"
            echo "  📥 正在自动降级到 PySpark 3.5.x..."
            pip install --quiet 'pyspark>=3.2.0,<4.0' --force-reinstall

            # 验证降级
            NEW_VERSION=$(python -c "import pyspark; print(pyspark.__version__)" 2>/dev/null)
            echo "  ✅ PySpark 已更新到 ${NEW_VERSION}"
            PYSPARK_VERSION="$NEW_VERSION"
        else
            echo "  ✓ pyspark ${PYSPARK_VERSION} 已安装"
        fi
    fi

    # 检查 networkx
    if ! python -c "import networkx" 2>/dev/null; then
        echo "  ⚠️  需要安装 networkx"
        NEED_INSTALL=1
    else
        echo "  ✓ networkx 已安装"
    fi

    # 检查 yaml
    if ! python -c "import yaml" 2>/dev/null; then
        echo "  ⚠️  需要安装 PyYAML"
        NEED_INSTALL=1
    else
        echo "  ✓ PyYAML 已安装"
    fi

    # 检查 graphframes
    if ! python -c "import graphframes" 2>/dev/null; then
        echo "  ⚠️  需要安装 graphframes"
        NEED_INSTALL=1
    else
        echo "  ✓ graphframes 已安装"
    fi

    # 检查 setuptools/distutils（Python 3.12+ 需要）
    if ! python -c "import distutils" 2>/dev/null; then
        echo "  ⚠️  需要安装 setuptools (提供 distutils)"
        NEED_INSTALL=1
    else
        echo "  ✓ setuptools/distutils 已安装"
    fi

    # 如果需要安装
    if [ $NEED_INSTALL -eq 1 ]; then
        echo ""
        echo "📥 正在安装依赖包..."
        pip install --quiet --upgrade pip
        pip install --quiet ${REQUIRED_PACKAGES}
        echo "✅ 依赖包安装完成"
    else
        echo "✅ 所有依赖包已就绪"
    fi
}

# 安装 GraphFrames JAR 文件到 Ivy 缓存（仅在使用 gf 模型时需要）
install_graphframes_jars() {
    # 只在使用 gf 模型时安装
    if [ "$MODEL_TYPE" != "gf" ]; then
        return 0
    fi

    echo ""
    echo "🔍 检查 GraphFrames JAR 文件..."

    # 本地 JAR 文件目录
    LOCAL_JARS_DIR="./graphframes_jars"

    # 检查本地 JAR 文件目录是否存在
    if [ ! -d "$LOCAL_JARS_DIR" ]; then
        echo "  ❌ 错误: 找不到本地 JAR 文件目录 ${LOCAL_JARS_DIR}"
        echo "     请确保 graphframes_jars 目录存在"
        return 1
    fi

    # 目标 Ivy 缓存目录
    IVY_JARS_DIR="$HOME/.ivy2/jars"
    IVY_CACHE_DIR="$HOME/.ivy2/cache"

    # 创建必要的目录
    mkdir -p "$IVY_JARS_DIR"
    mkdir -p "$IVY_CACHE_DIR"

    echo "  📦 正在安装 GraphFrames JAR 文件到 Ivy 缓存..."

    # 复制 jars 目录的文件
    COPIED_COUNT=0
    for jar_file in "$LOCAL_JARS_DIR/jars"/*.jar; do
        if [ -f "$jar_file" ]; then
            jar_name=$(basename "$jar_file")
            target_path="$IVY_JARS_DIR/$jar_name"

            # 检查文件是否已存在
            if [ -f "$target_path" ]; then
                echo "    ✓ ${jar_name} 已存在"
            else
                cp "$jar_file" "$target_path"
                echo "    ✅ ${jar_name} 已复制"
                COPIED_COUNT=$((COPIED_COUNT + 1))
            fi
        fi
    done

    # 复制 cache 目录的文件（保持目录结构）
    if [ -d "$LOCAL_JARS_DIR/cache" ]; then
        # 使用 rsync 或 cp -r 复制整个目录结构
        if command -v rsync &> /dev/null; then
            rsync -a --ignore-existing "$LOCAL_JARS_DIR/cache/" "$IVY_CACHE_DIR/" 2>/dev/null
            echo "    ✓ Ivy 元数据已同步"
        else
            cp -rn "$LOCAL_JARS_DIR/cache/"* "$IVY_CACHE_DIR/" 2>/dev/null || true
            echo "    ✓ Ivy 元数据已复制"
        fi
    fi

    if [ $COPIED_COUNT -gt 0 ]; then
        echo "  ✅ 成功安装 ${COPIED_COUNT} 个 JAR 文件"
    else
        echo "  ✓ 所有 JAR 文件已就绪（无需复制）"
    fi
}

# 创建必要目录
create_directories() {
    echo ""
    echo "=========================================="
    echo "检查输出目录"
    echo "=========================================="

    # 检查是否有需要清空的目录
    NEED_CLEAN=0
    DIRS_TO_CLEAN=""

    if [ -d "results" ] && [ "$(ls -A results 2>/dev/null)" ]; then
        NEED_CLEAN=1
        DIRS_TO_CLEAN="${DIRS_TO_CLEAN}  - results/\n"
    fi

    if [ -d "save_models" ] && [ "$(ls -A save_models 2>/dev/null)" ]; then
        NEED_CLEAN=1
        DIRS_TO_CLEAN="${DIRS_TO_CLEAN}  - save_models/\n"
    fi

    # 如果有内容需要清空，询问用户
    if [ $NEED_CLEAN -eq 1 ]; then
        echo ""
        echo "⚠️  警告：以下目录存在旧数据，将被清空："
        echo -e "$DIRS_TO_CLEAN"
        echo "是否继续？所有旧数据将被删除！"
        echo -n "请输入 [yes/y/回车 继续 | no/n 退出]: "

        read -r response

        # 转换为小写
        response=$(echo "$response" | tr '[:upper:]' '[:lower:]')

        # 检查用户响应
        if [ "$response" = "no" ] || [ "$response" = "n" ]; then
            echo ""
            echo "用户取消操作，退出程序"
            exit 0
        elif [ "$response" = "yes" ] || [ "$response" = "y" ] || [ -z "$response" ]; then
            echo ""
            echo "正在清空旧数据..."
            [ -d "results" ] && rm -rf results
            [ -d "save_models" ] && rm -rf save_models
            echo "✓ 旧数据已清空"
        else
            echo ""
            echo "无效输入，请输入 yes/y、no/n 或直接回车"
            echo "退出程序"
            exit 1
        fi
    else
        echo "✓ 输出目录为空，无需清理"
    fi

    # 创建所有必要目录
    echo ""
    echo "创建目录结构..."
    mkdir -p logs
    mkdir -p save_models
    mkdir -p results
    mkdir -p results/inter
    echo "✓ 目录创建完成"
}

# ============================================
# 解析运行参数（必须在主程序之前）
# ============================================

# 默认参数
PROVINCE="jiangsu"
MONTHID="202510"        # 改为与 generate_test_data.py 生成的月份一致
MODE="local"
MODEL_TYPE="nx"
ONLY_GRAPH="0"
ONLY_TV="0"

# 解析命令行参数
while [[ $# -gt 0 ]]; do
    case $1 in
        -p|--province)
            PROVINCE="$2"
            shift 2
            ;;
        -m|--monthid)
            MONTHID="$2"
            shift 2
            ;;
        --only-graph)
            ONLY_GRAPH="1"
            shift
            ;;
        --only-tv)
            ONLY_TV="1"
            shift
            ;;
        -h|--help)
            echo "用法: ./run_detection.sh [选项]"
            echo ""
            echo "选项:"
            echo "  -p, --province PROVINCE    省份 (默认: jiangsu)"
            echo "  -m, --monthid MONTHID      月份ID (默认: 202306)"
            echo "  --only-graph               只运行图计算"
            echo "  --only-tv                  只运行特征计算"
            echo "  -h, --help                 显示帮助信息"
            echo ""
            echo "示例:"
            echo "  ./run_detection.sh"
            echo "  ./run_detection.sh -p shandong -m 202308"
            echo "  ./run_detection.sh --only-graph"
            echo ""
            echo "首次运行会自动："
            echo "  - 创建虚拟环境"
            echo "  - 安装依赖包 (pyspark, networkx, PyYAML)"
            echo "  - 配置 Java (8+)"
            exit 0
            ;;
        *)
            echo "未知参数: $1"
            echo "使用 -h 或 --help 查看帮助"
            exit 1
            ;;
    esac
done

# ============================================
# 主程序
# ============================================

echo "=========================================="
echo "实名不实人检测系统 - 智能启动"
echo "=========================================="
echo ""

# 0. 检测操作系统
detect_os

# 0.1 设置 Java 路径
set_java_paths

# 1. 检查 Python
check_python_version

# 2. 检查 Java
check_java

# 3. 检查/创建虚拟环境
check_or_create_venv

# 4. 激活虚拟环境
activate_venv

# 5. 检查/安装依赖
check_or_install_packages

# 6. 安装 GraphFrames JAR 文件（如果使用 gf 模型）
# 从本地 graphframes_jars 目录复制到 Ivy 缓存，避免网络下载
install_graphframes_jars

# 7. 创建必要目录
create_directories

echo ""
echo "=========================================="
echo "环境准备完成，开始运行检测"
echo "=========================================="
echo ""

# 显示运行参数
echo "运行参数:"
echo "  省份: ${PROVINCE}"
echo "  月份: ${MONTHID}"
echo "  模式: ${MODE}"
echo "  只运行图计算: $([ "$ONLY_GRAPH" = "1" ] && echo "是" || echo "否")"
echo "  只运行特征计算: $([ "$ONLY_TV" = "1" ] && echo "是" || echo "否")"
echo ""
echo "日志文件: logs/detection_${PROVINCE}_${MONTHID}.out"
echo ""
echo "开始运行..."
echo ""

# 记录开始时间
START_TIME=$(date +%s)

# ============================================
# 运行检测程序
# ============================================

python3 main.py \
    --province ${PROVINCE} \
    --monthid ${MONTHID} \
    --mode ${MODE} \
    --model_type ${MODEL_TYPE} \
    --load_graph_model 0 \
    --only_graph ${ONLY_GRAPH} \
    --only_tv ${ONLY_TV} \
    --load_graph_result 0 \
    --load_tv_result 0

EXIT_CODE=$?

# ============================================
# 显示结果
# ============================================

echo ""
if [ $EXIT_CODE -eq 0 ]; then
    echo "=========================================="
    echo "✅ 运行成功！"
    echo "=========================================="
    echo ""
    echo "结果文件："

    if [ "$ONLY_GRAPH" = "1" ]; then
        echo "  - results/${PROVINCE}/graph_result_${PROVINCE}_${MONTHID}.csv"
    elif [ "$ONLY_TV" = "1" ]; then
        echo "  - results/${PROVINCE}/tv_result_${PROVINCE}_${MONTHID}.csv"
    else
        echo "  - results/${PROVINCE}/unreal_person_${PROVINCE}_${MONTHID}.csv"
    fi

    echo ""
    echo "中间结果:"
    echo "  - results/inter/${PROVINCE}/"
    echo ""
    echo "模型文件:"
    echo "  - save_models/graph_nx_${PROVINCE}_${MONTHID}.pkl"
    echo ""
else
    echo "=========================================="
    echo "❌ 运行失败 (退出码: ${EXIT_CODE})"
    echo "=========================================="
    echo ""
    echo "请查看日志文件:"
    echo "  cat logs/detection_${PROVINCE}_${MONTHID}.out"
    echo ""
fi

# ============================================
# 显示运行时间
# ============================================
END_TIME=$(date +%s)
ELAPSED=$((END_TIME - START_TIME))

# 转换为时分秒格式
HOURS=$((ELAPSED / 3600))
MINUTES=$(((ELAPSED % 3600) / 60))
SECONDS=$((ELAPSED % 60))

echo ""
echo "=========================================="
echo "⏱️  总耗时: ${HOURS}小时 ${MINUTES}分钟 ${SECONDS}秒 (共 ${ELAPSED} 秒)"
echo "=========================================="
echo ""

exit $EXIT_CODE
